package org.javaforever.infinity.domain;

import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.javaforever.infinity.utils.StringUtil;

public class Domain extends Class implements Comparable {
	protected List<Method> setters;
	protected List<Method> getters;
	protected String domainStr;
	protected Field domainId;
	protected Field domainName;
	protected Field active;
	protected String plural; 
	protected String dbPrefix = "";
	
	public int maxSerial(){
		int maxserial = 0;
		for (Field f:this.fields){
			if (f.getSerial() > maxserial) maxserial = f.getSerial();
		}
		return maxserial;
	}

	public Field getDomainId() {
		return domainId;
	}
	public void setDomainId(Field domainId) {
		this.domainId = domainId;
		this.domainId.setSerial(this.maxSerial() + 300);
	}
	
	public void addField(String name,String type){
		if ("active".equals(name)) {
			this.active = new Field(name, "boolean");
			this.active.setSerial(this.maxSerial() + 200);
			return;
		}
		if (name.equals(StringUtil.lowerFirst(this.getStandardName())+"Name")) {
			this.domainName = new Field(name, "String");
			this.domainName.setSerial(this.maxSerial() + 100);
			return;
		}
		if (name.equals(StringUtil.lowerFirst(this.getStandardName())+"Id")) {
			this.domainId = new Field(name, "long");
			this.domainId.setSerial(this.maxSerial() + 300);
			return;
		}
		this.fields.add(new Field(this.maxSerial()+100,name,type));
	}
	
	public void addField(String name,String type,String packageToken){
		this.addField(new Field(name,type,packageToken));
	}
	
	@Override
	public void addField(Field f){
		if ("active".equals(f.getFieldName())) {
			this.active = new Field(f.getFieldName(), "boolean");
			this.active.setSerial(this.maxSerial() + 200);
			return;
		}
		if (f.getFieldName().equals(StringUtil.lowerFirst(this.getStandardName())+"Name")) {
			this.domainName = new Field(f.getFieldName(), "String");
			this.domainName.setSerial(this.maxSerial() + 100);
			return;
		}
		if (f.getFieldName().equals(StringUtil.lowerFirst(this.getStandardName())+"Id")) {
			this.domainId = new Field(f.getFieldName(), "long");
			this.domainId.setSerial(this.maxSerial() + 300);
			return;
		}
		this.fields.add(new Field(this.maxSerial()+100,f.getFieldName(),f.getFieldType()));
	}
	
	@Override
	public String generateClassString(){
		StringBuilder sb = new StringBuilder();
		if (this.packageToken !=null && !"".equalsIgnoreCase(this.packageToken)) sb.append("package ").append(this.packageToken).append(".domain;\n\n");
		Set<String> imports = this.generateImportStrings();
		for (String s: imports){
			sb.append("import ").append(s).append(";\n");
		}
		sb.append("\n");
		
		sb.append("public class ");
		sb.append(capFirst(this.standardName) + " {\n");
		Iterator it =  this.getFields().iterator();

        while (it.hasNext()) {
        	Field f = (Field)it.next();
	        String name = f.getFieldName();
	        String type = f.getFieldType();
	        sb.append("\tprotected ").append(type).append(" ").append(lowerFirst(name) + ";\n");
        }
        
        it = this.getFields().iterator();
        while (it.hasNext()) {	
        	Field f = (Field)it.next();
	        String name = f.getFieldName();
	        String type = f.getFieldType();
	        sb.append("\tpublic ").append(type).append(" get").append(capFirst(name)).append("(){\n");
	        sb.append("\t\t return this.").append(name).append(";\n");
	        sb.append("\t}\n\n");
	        sb.append("\tpublic void set").append(capFirst(name)).append("(").append(type).append(" ").append(name).append("){\n");
	        sb.append("\t\t this.").append(name).append(" = ").append(name).append(";\n");
	        sb.append("\t}\n\n");
        }
        
        it = this.methods.iterator();
        while (it.hasNext()){
        	sb.append(((Method)it.next()).generateMethodString());
        	sb.append("\n");
        }
        sb.append("}\n");
		return sb.toString();
	}
	
	public String capFirst(String value){
		return value.substring(0, 1).toUpperCase()+value.substring(1);
	}
	
	public String lowerFirst(String value){
		return value.substring(0, 1).toLowerCase()+value.substring(1);
	}
	
	@Override
	public int compareTo(Object o) {
		String myName = this.getStandardName();
		String otherName = ((Domain)o).getStandardName();
		return myName.compareTo(otherName);
	}
	
	@Override
	public boolean equals(Object o){
		return (this.compareTo(o)==0);
	}
	public List<Method> getSetters() {
		return setters;
	}
	public void setSetters(List<Method> setters) {
		this.setters = setters;
	}
	public List<Method> getGetters() {
		return getters;
	}
	public void setGetters(List<Method> getters) {
		this.getters = getters;
	}
	public String getDomainStr() {
		return domainStr;
	}
	public void setDomainStr(String domainStr) {
		this.domainStr = domainStr;
	}
	public Field getDomainName() {
		return domainName;
	}
	public void setDomainName(Field domainName) {
		this.domainName = domainName;
	}
	public Field getActive() {
		return active;
	}
	public void setActive(Field active) {
		this.active = active;
	}
	public String getPlural() {
		if (this.plural == null || "".equals(this.plural))
			return this.getStandardName() + "s";
		else 
			return plural;
	}
	public void setPlural(String plural) {
		this.plural = plural;
	}
	
	public Type getType(){
		Type retType = new Type(this.getStandardName(),this.getPackageToken());
		return retType;
	}
	
	@Override
	public Set<Field> getFields(){
		Set<Field> set = new TreeSet<Field>();
		set.addAll(super.getFields());		
		if (this.domainName != null) {
			this.domainName.setSerial(this.maxSerial() + 100);
			set.add(this.domainName);
		}
		if (this.active != null) {
			this.active.setSerial(this.maxSerial() + 200);
			set.add(this.active);
		}
		if (this.domainId != null) {
			this.domainId.setSerial(this.maxSerial() + 300);
			set.add(this.domainId);
		}
		return set;
	}
	
	public Set<Field> getFieldsWithoutId(){
		Set<Field> set = new TreeSet<Field>();
		set.addAll(super.getFields());		
		if (this.domainName != null) {
			this.domainName.setSerial(this.maxSerial() + 100);
			set.add(this.domainName);
		}
		if (this.active != null) {
			this.active.setSerial(this.maxSerial() + 200);
			set.add(this.active);
		}
		return set;
	}
	
	public String generateTypeVarString(){
		return StringUtil.capFirst(this.getStandardName()) + " " + StringUtil.lowerFirst(this.getStandardName());
	}
	
	public Field getField(String fieldName){
		for (Field f : this.getFields()){
			if (f.getFieldName().equals(fieldName)){
				return f;
			}
		}
		return null;
	}

	public String getDbPrefix() {
		return dbPrefix;
	}

	public void setDbPrefix(String dbPrefix) {
		this.dbPrefix = dbPrefix;
	}
}
